<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="keywords" content="HTML5,graph,canvas,3D,Fractal">
<title>Koch Curve Extended to 3D</title>
<script src="js/sylvester.js" type="text/javascript"></script>
<script src="js/glUtils.js" type="text/javascript"></script>
<STYLE type="text/css">
 	body {
 		background-image: url("img/snow.png");
		background-repeat: repeat;
 		background-color: #AAEEFF;
	}
	h1 {
		font-size:15px;
		line-height: 70%;
	}
	h3 {
		font-size:12px;
	}
	#ctrlpanel {
		width: 80%;
		background-color: #AACCEE;
		margin-left:auto;
		margin-right:auto;
		text-align:left;
		border: 9px #555577 solid;
		border-style: ridge groove inset;
	}
	#command {
		padding : 5px;
	}
	#chart {
		margin-left:auto;
		margin-right:auto;
		text-align:left;
	}

	.submitButton {
		background-color: #ffff00;
		border: 2px solid #444422;
		color: #000033;
	}
	.argButton {
		background-color: #CCCCFF;
		border: 2px solid #333311;
		color: #000033;
	}
	td {
		vertical-align: top;
		margin-left:20px;
		margin-right:20px;
		text-align:left;
	}
		
</STYLE>

<script id="shader-fs" type="x-shader/x-fragment">
	#ifdef GL_ES
	precision highp float;
	#endif

	varying vec4 vColor;

	void main(void) {
		gl_FragColor = vColor;
	}
</script>

<script id="shader-vs" type="x-shader/x-vertex">
	attribute vec3 aVertexPosition;
	attribute vec4 aVertexColor;

	uniform mat4 uMVMatrix;
	uniform mat4 uPMatrix;

	varying vec4 vColor;

	void main(void) {
		gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);
		vColor = aVertexColor;
	}
</script>
<script>
	var	level = 1;
	function setNaviPath(isOut) {
		var mainWindow = window.parent;
		if (isOut == false) {
			mainWindow.document.getElementById('path' + level + "lnk").innerHTML = "";
//			mainWindow.document.getElementById('path' + level + "lnk").href = "";
			mainWindow.document.getElementById('path' + level + "txt").innerHTML = "&gt; Fractal ";
			for (var i = 2; i < 5; i++) {
				mainWindow.document.getElementById('path' + i + "lnk").innerHTML = "";
//				mainWindow.document.getElementById('path' + i + "lnk").href = "";
				mainWindow.document.getElementById('path' + i + "txt").innerHTML = "";
			}
		} 
//		else {
//			var tmp = mainWindow.document.getElementById('path' + level + "lnk");
//			tmp.innerHTML = "&gt; Car Mileage ";
//			tmp.href = "javascript:void(0)";
//			mainWindow.document.getElementById('path' + level + "lnk").innerHTML = "> Car Mileage ";
//			mainWindow.document.getElementById('path' + level + "lnk").href = "./graph.html";
//			mainWindow.document.getElementById('path' + level + "txt").innerHTML = "";
//			mainWindow.document.getElementById('path' + (level + 1) + "lnk").innerHTML = "";
//			mainWindow.document.getElementById('path' + (level + 1) + "txt").innerHTML = "&gt; Data ";
//		}
	}
</script>
<script>

	//	 var lastX = context.canvas.width * Math.random();
	//	 var lastY = context.canvas.height * Math.random();
	var gl;
	var shaderProgram;
	var triangleVertexPositionBuffer;
	var rTri = 0;
	var vertices;
	var	vInx;
	var	pInt;

	
	function childTri(level,p1,p2,p3) {
		vertices[vInx * 3 + 0] = p1[0];
		vertices[vInx * 3 + 1] = p1[1];
		vertices[vInx * 3 + 2] = p1[2];
		vertices[vInx * 3 + 3] = p2[0];
		vertices[vInx * 3 + 4] = p2[1];
		vertices[vInx * 3 + 5] = p2[2];
		vertices[vInx * 3 + 6] = p3[0];
		vertices[vInx * 3 + 7] = p3[1];
		vertices[vInx * 3 + 8] = p3[2];
		vInx += 3;
				
		level = level - 1;
		if (level == 0) {
			return;
		}
		var	i;
		var pp1 = new Array();
		var pp2 = new Array();
		var pp3 = new Array();
		var pp4 = new Array();
		for (i = 0; i < 3; i++) {
			pp1[i] = ((p2[i] + p3[i])/2 + p1[i] * 2) /3;
		}
		for (i = 0; i < 3; i++) {
			pp2[i] = ((p3[i] + p1[i])/2 + p2[i] * 2) /3;
		}
		for (i = 0; i < 3; i++) {
			pp3[i] = ((p1[i] + p2[i])/2 + p3[i] * 2) /3;
		}
//		var a = new Array(p2[0]-p1[0],p2[1]-p1[1],p2[2]-p1[2]);
//		var b = new Array(p3[0]-p1[0],p3[1]-p1[1],p3[2]-p1[2]);
		var b = new Array(pp2[0]-pp1[0],pp2[1]-pp1[1],pp2[2]-pp1[2]);
		var a = new Array(pp3[0]-pp1[0],pp3[1]-pp1[1],pp3[2]-pp1[2]);		
		var proj = new Array(a[1] * b[2] - a[2] * b[1] , a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]);
		var r = Math.sqrt(proj[0] * proj[0] + proj[1] * proj[1] + proj[2] * proj[2])
		var s = Math.sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2]);
		for (i = 0; i < 3; i++ ) {
			pp4[i] = (pp1[i] + pp2[i] + pp3[i]) / 3 + s * Math.sin(Math.acos(1 / 3)) * Math.sqrt(3) / 2 * proj[i] 

/ r;
		}
		childTri(level,pp1,pp2,pp4);
		childTri(level,pp2,pp3,pp4);
		childTri(level,pp3,pp1,pp4);		

	}

	function drawGraph() {
		var	level;
		var	xoffset = 100;
		var	yoffset = 100;
		var	zoffset = 100;
		var	edge = 3;
		var	p1;
		var	p2;
		var	p3;
		var	p4;

		if (pInt) {
			clearInterval(pInt);
		}
			
		p1 = new Array(0.0,				Math.sqrt(3) * edge /2,			0.0);
		p2 = new Array(-0.5 * edge,	0.0,									0.0);
		p3 = new Array(0.5 * edge,	0.0,									0.0);
		p4 = new Array(0.0,				edge /3,							

	(Math.sqrt(3) * edge * Math.sin(Math.acos(1 / 3))/2)); 


		// GL
		var canvas = document.getElementById("gra");
//		initGL(canvas);
		try {
			gl = canvas.getContext("webgl"); //webgl"experimental-webgl"moz-glweb20
		} catch(e) {
			gl = null;
		}
		if (!gl) {
			try {
				gl = canvas.getContext("experimental-webgl"); //webgl"experimental-webgl"moz-glweb20
			} catch(e) {
				gl = null;
			}
		}
		if (!gl) {
			alert("Could not initialise WebGL, sorry :-(");
			return;
		}
		gl.viewportWidth = canvas.width;
		gl.viewportHeight = canvas.height;


//		initShaders();
		var fragmentShader = getShader(gl, "shader-fs");
		var vertexShader = getShader(gl, "shader-vs");

		shaderProgram = gl.createProgram();
		gl.attachShader(shaderProgram, vertexShader);
		gl.attachShader(shaderProgram, fragmentShader);
		gl.linkProgram(shaderProgram);

		if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
			alert("Could not initialise shaders");
			return;
		}

		gl.useProgram(shaderProgram);
		shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
		gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

		shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");
		gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

		shaderProgram.pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix");
		shaderProgram.mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix");

//		initBuffers();
		triangleVertexPositionBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
//		vertices = [
//				 0.0,	1.0,	0.0,
//				-1.0, -1.0,	0.0,
//				 1.0, -1.0,	0.0
//			p1[0],	p1[1],	p1[2],
//			p2[0],	p2[1],	p2[2],
//			p3[0],	p3[1],	p3[2],
//
//			p2[0],	p2[1],	p2[2],
//			p4[0],	p4[1],	p4[2],
//			p3[0],	p3[1],	p3[2],
//
//			p3[0],	p3[1],	p3[2],
//			p4[0],	p4[1],	p4[2],
//			p1[0],	p1[1],	p1[2],
//
//			p4[0],	p4[1],	p4[2],
//			p2[0],	p2[1],	p2[2],
//			p1[0],	p1[1],	p1[2],
//		];
		level = document.getElementById("selectGraph0").value;
		vInx = 0;
		vertices = new Array();
		childTri(level, p1,p2,p3);
		childTri(level, p2,p4,p3);
		childTri(level, p3,p4,p1);
		childTri(level, p4,p2,p1);
		
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);

		triangleVertexPositionBuffer.itemSize = 3;
		triangleVertexPositionBuffer.numItems = vInx;

		triangleVertexColorBuffer = gl.createBuffer();
		gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
//		var colors = [
//				1.0, 0.0, 0.0, 1.0,
//				0.0, 1.0, 0.0, 1.0,
//				0.0, 0.0, 1.0, 1.0,

//				1.0, 0.0, 0.0, 1.0,
//				0.0, 1.0, 0.0, 1.0,
//				0.0, 0.0, 1.0, 1.0,

//				1.0, 0.0, 0.0, 1.0,
//				0.0, 1.0, 0.0, 1.0,
//				0.0, 0.0, 1.0, 1.0,

//				1.0, 0.0, 0.0, 1.0,
//				0.0, 1.0, 0.0, 1.0,
//				0.0, 0.0, 1.0, 1.0,
//		];
		var colors = new Array(vInx * 4);
		for (var i = 0; i < (vInx +1) * 4; i++) {
			j = i - parseInt(i/4) * 4;
			k = parseInt(i/4) - parseInt(parseInt(i/4)/3) * 3;
			if (j == 3) {
				colors[i] = 1.0;
			} else if (j == k) {
				colors[i] = 1.0;
			} else {
				colors[i] = 0.0;
			}
	   }			
		gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
		triangleVertexColorBuffer.itemSize = 4;
		triangleVertexColorBuffer.numItems = vInx;


		gl.clearColor(0.5, 0.5, 0.5, 1.0);
		gl.clearDepth(1.0)
		gl.enable(gl.DEPTH_TEST);
		gl.depthFunc(gl.LEQUAL);


		lastTime = new Date().getTime();
		pInt=setInterval(tick, 200);
//		tick();
	}

	function getShader(gl, id) {
			var shaderScript = document.getElementById(id);
			if (!shaderScript) {
					return null;
			}

			var str = "";
			var k = shaderScript.firstChild;
			while (k) {
					if (k.nodeType == 3)
							str += k.textContent;
					k = k.nextSibling;
			}

			var shader;
			if (shaderScript.type == "x-shader/x-fragment") {
					shader = gl.createShader(gl.FRAGMENT_SHADER);
			} else if (shaderScript.type == "x-shader/x-vertex") {
					shader = gl.createShader(gl.VERTEX_SHADER);
			} else {
					return null;
			}

			gl.shaderSource(shader, str);
			gl.compileShader(shader);

			if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
					alert(gl.getShaderInfoLog(shader));
					return null;
			}

			return shader;
	}
	
	
	function tick() {
		drawScene();
		animate();
	}

	var lastTime = 0;
	function animate() {
		var timeNow = new Date().getTime();
		if (lastTime != 0) {
			var elapsed = timeNow - lastTime;

			rTri += (90 * elapsed) / 1000.0;
		}
		lastTime = timeNow;
	}
	
	
	
	function drawScene() {
	 gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
		gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

		perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 100.0);
		loadIdentity();

//		mvTranslate([-1.5, 0.0, -7.0])
		mvTranslate([0.0, 0.0, -7.0])

		mvPushMatrix();
		mvRotate(rTri, [0, 1, 0]);

		gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, triangleVertexPositionBuffer.itemSize, 

gl.FLOAT, false, 0, 0);

		gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer);
		gl.vertexAttribPointer(shaderProgram.vertexColorAttribute, triangleVertexColorBuffer.itemSize, gl.FLOAT, 

false, 0, 0);

		setMatrixUniforms();
		gl.drawArrays(gl.TRIANGLES, 0, triangleVertexPositionBuffer.numItems);

		mvPopMatrix();
 
	}

	
	var mvMatrix;

	function loadIdentity() {
		mvMatrix = Matrix.I(4);
	}

	function multMatrix(m) {
		mvMatrix = mvMatrix.x(m);
	}

	function mvTranslate(v) {
		var m = Matrix.Translation($V([v[0], v[1], v[2]])).ensure4x4();
		multMatrix(m);
	}


	var pMatrix;
	function perspective(fovy, aspect, znear, zfar) {
		pMatrix = makePerspective(fovy, aspect, znear, zfar);
	}


	var mvMatrixStack = [];

	function mvPushMatrix(m) {
		if (m) {
			mvMatrixStack.push(m.dup());
			mvMatrix = m.dup();
		} else {
			mvMatrixStack.push(mvMatrix.dup());
		}
	}

	function mvPopMatrix() {
		if (mvMatrixStack.length == 0) {
			throw "Invalid popMatrix!";
		}
		mvMatrix = mvMatrixStack.pop();
		return mvMatrix;
	}
	function mvRotate(ang, v) {
		var arad = ang * Math.PI / 180.0;
		var m = Matrix.Rotation(arad, $V([v[0], v[1], v[2]])).ensure4x4();
		multMatrix(m);
	}

  function setMatrixUniforms() {
    gl.uniformMatrix4fv(shaderProgram.pMatrixUniform, false, new Float32Array(pMatrix.flatten()));
    gl.uniformMatrix4fv(shaderProgram.mvMatrixUniform, false, new Float32Array(mvMatrix.flatten()));
  }

	function blank() {
		var context = document.getElementById("gra").getContext('experimental-webgl');
//		context.fillStyle = 'rgba(255,255,255,0.8)';
//		context.fillRect(0, 0, context.canvas.width, context.canvas.height);
		 /*  */

	}
</script>
</head>
<body onload="localStorage.setItem('tdssg' + Date(), 'Open Fractal page');setNaviPath(false);"
	onunload="localStorage.setItem('tdssg' + Date(), 'Exit from this Fractal page');"><!-- geoguide start --><div align=center><script language="JavaScript">var jps=382116067;var jpt=1365143562</script><script language="JavaScript" src="http://bc.geocities.yahoo.co.jp/js/gg.js"></script></div><!-- geoguide end -->
<h1>Koch Curve Extended to 3D</h1>
<h3>Please browse with HTML 5 browser</h3>
<div id="container">
<div id="ctrlpanel">
		<table id ="command">
			<tr>
			<td>
			</td>
			<td>
			<strong>--Submit--&#xA0;&#xA0;&#xA0;</strong>
			<input type="button" class="submitButton"  value="Draw" onClick="localStorage.setItem('tdssg' + Date(), 'Click Draw Button on Fractal page');drawGraph();">
			</td>
			<td>&#xA0;&#xA0;&#xA0;&#xA0;
			</td>
			<td>
			<strong>--Arguments--&#xA0;&#xA0;&#xA0;</strong>Select Nest Level&#xA0;&#xA0;
				<select class="argButton" id="selectGraph0">
				<option value="1">1</option>
				<option value="2">2</option>
				<option value="3" selected>3</option>
				<option value="4">4</option>
				<option value="5">5</option>
				<option value="6">6</option>
				<option value="7">7</option>
				<option value="8">8</option>
				<option value="9">9</option>
				</select>
			</td>
			<td>
			</td>
			</tr>
		</table>
</div>
<br />
<table id="chart">
	<tr>
		<td><canvas id="gra" width="320" height="320"></canvas></td>
	</tr>
</table>			
</div>

</body>

</html>
 